home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / dpmi_lib.zip / DPMIUTIL.C < prev    next >
C/C++ Source or Header  |  1991-11-06  |  14KB  |  612 lines

  1. /* This file is DPMIUTIL.C
  2. ** Copyright (c) Rainer Schnitker 10/91
  3. */
  4.  
  5. /* This file need Turbo C to compile,
  6. ** but there are only TurboC specials like  asm { statement }
  7. ** Function used : allocmem(),MK_FP(),FP_SEG(),FP_OFF()
  8. ** Compile options : -ms (because of other segments in protected mode)
  9. **                   -2  (protected mode)
  10. **                   -B  (Assembler lines)
  11. */
  12.  
  13. #include "DPMI.H"
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <dos.h>
  17.  
  18. /* CPU switching for DPMI 0.9 */
  19.  
  20. void real_to_protected()
  21. {
  22. unsigned int speicherseg;
  23. WORD rax,seg,off,hostreq;
  24. DWORD PM_jump ;
  25. int status;
  26. asm {   mov ax,1687h                            /* DMPI supported ? */
  27.         int 2fh
  28.         mov rax,ax
  29.         mov off,di 
  30.         mov seg,es 
  31.         mov hostreq,si }
  32. if (rax){
  33.         printf("no dpmi supported\n");
  34.         exit(1);
  35.         }
  36.  
  37. PM_jump = (long)seg ;
  38. PM_jump <<= 16 ;
  39. PM_jump += (long)off ; 
  40.  
  41. status=allocmem(hostreq,&speicherseg);          /* for DPMI-Stack */
  42. if (status!=-1) {                               /* reserve        */
  43.                 printf("allocmem() error\n");
  44.                 exit(1); 
  45.                 }
  46. asm {   mov es,speicherseg ;
  47.         mov ax,0 ;
  48.         call DWORD PTR PM_jump ;    
  49.         jnc PMOK ; }
  50.  
  51. printf("Can't switch to Protected Mode!");
  52. exit(1);
  53.  
  54. PMOK:
  55. printf("CPU in Protected Mode\n");
  56. printf("CS=%X DS=%X ES=%X SS=%X\n",_CS,_DS,_ES,_SS);
  57.  
  58. _BL=0x23 ;          /* Control Break -> protected_to_real() */
  59. _CX=_CS ;
  60. asm mov dx,OFFSET MYINT ;
  61. DPMI(0x0205);  
  62.  
  63. }
  64.  
  65. void protected_to_real()
  66. {
  67. printf("CPU in Real Mode\n");
  68. asm MYINT LABEL byte ;
  69. asm {   mov ax,4C00h
  70.     int 21h   }     /* program ends here */
  71. }
  72.  
  73. /* LDT Descriptor management services  DPMI 0.9 */
  74.  
  75. WORD AllocLDT(WORD anzahl)
  76. {
  77. _CX=anzahl;
  78. DPMI(0x0000);
  79. asm jnc OKallocldt ;
  80. return 0;
  81. OKallocldt:
  82. return _AX;
  83. }
  84.  
  85. int FreeLDT(WORD sel)
  86. {
  87. _BX=sel;
  88. DPMI(0x0001);
  89. asm jnc OKfreeldt;
  90. return -1;
  91. OKfreeldt:
  92. return 0;
  93. }
  94.  
  95. WORD SegtoSel(WORD seg)
  96. {
  97. _BX=seg;
  98. DPMI(0x0002);
  99. asm jnc OKsegsel;
  100. return 0;
  101. OKsegsel:
  102. return _AX;
  103. }
  104.  
  105. WORD SelInc()
  106. {
  107. DPMI(0x0003);
  108. return _AX ;
  109. }
  110.  
  111. int LockSel(WORD sel)
  112. {
  113. _BX=sel ;
  114. DPMI(0x0004);
  115. asm jnc OKlocksel;
  116. return -1;
  117. OKlocksel:
  118. return 0;
  119. }
  120.  
  121. int UnlockSel(WORD sel)
  122. {
  123. _BX=sel ;
  124. DPMI(0x0005);
  125. asm jnc OKunlocksel;
  126. return -1;
  127. OKunlocksel:
  128. return 0;
  129. }
  130.  
  131. DWORD GetBaseAddress(WORD sel)
  132. {
  133. _BX=sel;
  134. DPMI(0x0006);
  135. asm jnc OKgetbase;
  136. return 0;
  137. OKgetbase:
  138. return ( (DWORD)_DX | ( (DWORD)_CX <<16 ) );
  139. }
  140.  
  141. int SetBaseAddress(WORD sel,DWORD address)
  142. {
  143. _CX=(WORD) (address>>16);
  144. _DX=(WORD) address ; 
  145. _BX=sel;
  146. DPMI(0x0007);
  147. asm jnc OKsetbase;
  148. return -1;
  149. OKsetbase:
  150. return 0;
  151. }
  152.  
  153. int SetLimit(WORD sel,DWORD limit)
  154. {
  155. _BX=sel;
  156. _CX=(WORD) (limit>>16) ;
  157. _DX=(WORD) limit ;
  158. DPMI(0x0008);
  159. asm jnc OKsetlimit;
  160. return -1;
  161. OKsetlimit:
  162. return 0;
  163. }
  164.  
  165. int SetAccess(WORD sel,BYTE access,BYTE extaccess)
  166. {
  167. _BX=sel;
  168. _CL=access;
  169. _CH=extaccess;
  170. DPMI(0x0009);
  171. asm jnc OKsetaccess;
  172. return -1;
  173. OKsetaccess:
  174. return 0;
  175. }
  176.  
  177. WORD CreatAlias(WORD segsel)
  178. {
  179. _BX=segsel;
  180. DPMI(0x000a);
  181. asm jnc OKcreatalias;
  182. return 0;
  183. OKcreatalias:
  184. return _AX ;
  185. }
  186.  
  187. int GetDescriptor(WORD sel,DESCRIPTOR *d)
  188. {
  189. asm push es ;
  190. _BX=sel;
  191. _ES=FP_SEG(d);
  192. _DI=FP_OFF(d);
  193. DPMI(0x000b);
  194. asm pop es ;
  195. asm jnc OKgetdisc ;
  196. return -1;
  197. OKgetdisc:
  198. return 0;
  199. }
  200.  
  201. int SetDescriptor(WORD sel,DESCRIPTOR *d)
  202. {
  203. asm push es ;
  204. _BX=sel;
  205. _ES=FP_SEG(d);
  206. _DI=FP_OFF(d);
  207. DPMI(0x000c);
  208. asm pop es ;
  209. asm jnc OKsetdisc ;
  210. return -1;
  211. OKsetdisc:
  212. return 0;
  213. }
  214.  
  215. int AllocSpecialLDT(WORD sel)
  216. {
  217. _BX=sel;
  218. DPMI(0x000d);
  219. asm jnc OKspecial;
  220. return -1 ;
  221. OKspecial:
  222. return 0 ;
  223. }
  224.  
  225. /* Interrupt Services  DPMI 0.9 */
  226.  
  227. int GetExceptionVector(BYTE b,WORD *sel,WORD *off)
  228. {
  229. _BL=b;
  230. DPMI(0x0202);
  231. asm jnc OKgetexeption;
  232. return -1;
  233. OKgetexeption:
  234. *sel=_CX;
  235. *off=_DX;
  236. return 0;
  237. }
  238.  
  239. int SetExceptionVector(BYTE b,WORD sel,WORD off)
  240. {
  241. _BL=b;
  242. _CX= sel;
  243. _DX= off;
  244. DPMI(0x0203); 
  245. asm jnc OKsetexeption;
  246. return -1;
  247. OKsetexeption:
  248. return 0;
  249. }
  250.  
  251. int GetPMinterruptVector(BYTE b,WORD *sel,WORD *off)
  252. {
  253. _BL=b;
  254. DPMI(0x0204); 
  255. asm jnc OKgetpmiv;
  256. return -1;
  257. OKgetpmiv:
  258. *sel=_CX;
  259. *off=_DX;
  260. return 0;
  261. }
  262.  
  263. int SetPMinterruptVector(BYTE b,WORD sel,WORD off)
  264. {
  265. _BL=b;
  266. _CX= sel;
  267. _DX= off;
  268. DPMI(0x0205); 
  269. asm jnc OKsetpmiv;
  270. return -1;
  271. OKsetpmiv:
  272. return 0;
  273. }
  274.  
  275. /* Memory managment services DPMI 0.9 */
  276.  
  277. void getfreeinfo(FREEMEMINFO *fm)
  278. {
  279. asm push es ;
  280. _ES=FP_SEG(fm) ; _DI=FP_OFF(fm) ;
  281. DPMI(0x500);
  282. asm pop es ;
  283. }
  284.  
  285. void printfreeinfo(FREEMEMINFO *fm)
  286. {
  287. printf("Largest available block           : %lu Byte \n",fm->i1);
  288. printf("Number free pages                 : %3lu = %4lu KB\n",fm->i2,fm->i2*4);
  289. printf("Number free pages to lock         : %3lu = %4lu KB\n",fm->i3,fm->i3*4);
  290. printf("Number pages of linear addr space : %3lu = %4lu KB\n",fm->i4,fm->i4*4);
  291. printf("Number pages not locked           : %3lu = %4lu KB\n",fm->i5,fm->i5*4);
  292. printf("Number pages not used             : %3lu = %4lu KB\n",fm->i6,fm->i6*4);
  293. printf("Number pages managed by the Dpmi  : %3lu = %4lu KB\n",fm->i7,fm->i7*4);
  294. printf("Number pages free addr space      : %3lu = %4lu KB\n",fm->i8,fm->i8*4);
  295. printf("Number pages in swapfile          : %3lu = %4lu KB\n",fm->i9,fm->i9*4);
  296. }
  297.  
  298. DWORD GlobalAlloc(DWORD bytes,DWORD *memhandle)
  299. {  
  300. _BX=(WORD) (bytes>>16);
  301. _CX=(WORD) bytes ;
  302. DPMI(0x501);
  303. asm jnc OKalloc;
  304. return 0 ;
  305. OKalloc:
  306. *memhandle = (DWORD)_CX | ( (DWORD)_BX <<16 ) ;
  307. return ( (DWORD)_DI | ( (DWORD)_SI <<16 ) );
  308. }
  309.  
  310. int GlobalFree(DWORD handle)
  311. {
  312. _SI=(WORD) (handle>>16);
  313. _DI=(WORD) handle ;
  314. DPMI(0x0502);
  315. asm jnc OKFREE ;
  316. return -1 ;
  317. OKFREE:
  318. return 0 ;
  319. }
  320.  
  321. /* Page locking services  DPMI 0.9 */
  322.  
  323. int LockLinRegion(DWORD size,DWORD address)
  324. {
  325. _BX=(WORD) (address>>16);
  326. _CX=(WORD) address;
  327. _SI=(WORD) (size>>16);
  328. _DI=(WORD) size;
  329. DPMI(0x0600);
  330. asm jnc oklocklin;
  331. return -1;
  332. oklocklin:
  333. return 0;
  334. }
  335.  
  336. int UnlockLinRegion(DWORD size,DWORD address)
  337. {
  338. _BX=(WORD) (address>>16);
  339. _CX=(WORD) address;
  340. _SI=(WORD) (size>>16);
  341. _DI=(WORD) size;
  342. DPMI(0x0600);
  343. asm jnc okunlocklin;
  344. return -1;
  345. okunlocklin:
  346. return 0;
  347. }
  348.  
  349. /* Other multiplex int 2F */
  350.  
  351. void Yield()    /* give control to operating system (like GetMassage) */
  352. {
  353.     _AX=0x1680 ;
  354.     asm int 2Fh ;
  355. }
  356.  
  357. /* Protected mode API */
  358.  
  359. DWORD lsl(WORD sel)  /* load selector limit */
  360. {
  361. asm {   db 66h;
  362.         sub ax,ax;      /* sub eax,eax */
  363.         db 66h;
  364.         mov bx,ax;      /* mov ebx,eax */
  365.         mov bx,sel
  366.         db 66h;
  367.         lsl ax,bx;      /* lsl eax,ebx */
  368.         db 66h;
  369.         mov dx,ax ;     /* mov eax,eax  ax:low word */
  370.         db 66h ;
  371.         shr dx,16       /* shr edx,16   dx:high word */
  372.     }
  373. }
  374.  
  375. WORD lsl16(WORD sel)  /* 16-bit version of lsl for 80286 */
  376. {
  377.     asm sub ax,ax
  378.     asm lsl ax,sel
  379.     return _AX ;
  380. }
  381.  
  382. WORD lar(WORD sel)  /* load access rights */
  383. {
  384.     asm sub ax,ax ;
  385.     asm lar ax,sel;
  386.     asm shr ax,8 ;
  387.     return _AX ;
  388. }
  389.  
  390. WORD verr(WORD sel)  /* verify read */
  391. {
  392. asm mov ax,1 ;
  393. asm verr sel ;
  394. asm je okr ;
  395. asm dec ax ;
  396. okr:
  397. return _AX ;
  398. }
  399.  
  400. WORD verw(WORD sel)  /* verify write */
  401. {
  402. asm mov ax,1 ;
  403. asm verw sel ;
  404. asm je okw ;
  405. asm dec ax ;
  406. okw:
  407. return _AX ;
  408. }
  409.  
  410. void sgdt(GDTR *g)  /* save gdt table */
  411. {
  412. asm mov si,g ;
  413. asm sgdt [si] ;
  414. }
  415.  
  416. void sidt(GDTR *g)   /* save idt table */
  417. {
  418. asm mov si,g ;
  419. asm sidt [si] ;
  420. }
  421.  
  422. WORD sldt(void)          /* save ldt-selector */
  423. {
  424. asm sldt ax ;
  425. return _AX ;
  426. }
  427.  
  428. WORD str(void)           /* save task-register */
  429. {
  430. asm str ax ;
  431. return _AX ;
  432. }
  433.  
  434. /* Protected mode utilities */
  435.  
  436. void far * incfp(void far *a)  /* get next selector */
  437. {
  438.     FP_SEG(a)+=SelInc();
  439.     return(a);
  440. }
  441.  
  442. void far * decfp(void far *a)  /* get previous selector */
  443. {
  444. FP_SEG(a)-=SelInc();
  445. return(a);
  446. }
  447.  
  448. void printdescriptor(DESCRIPTOR d)
  449. {
  450. printf("b=%02X%02X%04X lim=%01X%04X p=%u dpl=%u %s t4=%X t=%u %s %s\n",
  451.         d.base_hi,d.base_mi,d.base_lo,
  452.         d.lim_hi&15,d.lim_lo,
  453.         (d.access&128)>>7,
  454.         (d.access&96)>>5,
  455.         (d.access&16) ? "MEMseg" : "SYSseg",
  456.         (d.access&15),
  457.         (d.access&7),
  458.         (d.lim_hi &  64) ? "32bit" : "16bit" ,
  459.         (d.lim_hi & 128) ? "paging": " " );
  460. }
  461.  
  462. void farcopy(void far *dest,void far *source,DWORD bytes)
  463. {
  464.     unsigned long i ;
  465.  
  466.     bytes++;                    /* if bytes %2 = 1 */
  467.     bytes>>=1;
  468.     poke( FP_SEG(dest),FP_OFF(dest),peek(FP_SEG(source),FP_OFF(source)) );
  469.     for (i=1; i< bytes ; i++) {
  470.         FP_OFF(dest)+=2 ;
  471.         if (FP_OFF(dest)==0) dest=incfp(dest);
  472.         FP_OFF(source)+=2 ;
  473.         if (FP_OFF(source)==0) source=incfp(source);
  474.         poke( FP_SEG(dest),FP_OFF(dest),peek(FP_SEG(source),FP_OFF(source)) );
  475.         }
  476. }
  477.  
  478. /* high level C-function using DPMI-API */
  479. /* malloc,free */
  480.  
  481. #define PAGESIZE 4096
  482. #define PAGEBUCKET 11
  483. #define NBUCKETS 30
  484. #define MAGIC 0xFFF0
  485.  
  486. union overhead {
  487.                 struct {
  488.                         WORD page;
  489.                         WORD offset;
  490.                 } free ;
  491.                 struct {
  492.                         WORD magic ;
  493.                         WORD index ;
  494.                 } use ;
  495.         } ;
  496.  
  497. static union overhead nextf[NBUCKETS];
  498.  
  499. void far * morepages(WORD bucket)
  500. {
  501. WORD nblks,i,page,nsel,nextpage;
  502. DWORD sz,handle,memaddress;
  503.  
  504. sz = ((DWORD)1) << (bucket + 2) ;
  505.  
  506. if (sz<PAGESIZE)    /* 1st case : divide 4K-Page in sz-big blocks */
  507.         {
  508.         if ((handle=GlobalAlloc(PAGESIZE,&memaddress))==0) 
  509.                 return NULL ;
  510.         if ( (page=AllocLDT(1)) ==0) {    /* no more selectors ? */
  511.             GlobalFree(handle);           /* free memory */
  512.             return NULL;
  513.             }
  514.         if (SetBaseAddress(page,memaddress)==-1) return NULL;
  515.         if (SetLimit(page,PAGESIZE-1)==-1) return NULL;
  516.  
  517.         nblks = PAGESIZE / (WORD)sz ;     /* number of pieces */
  518.         nblks--;
  519.         nextf[bucket].free.page=page;     /* freelist -> second block */
  520.         nextf[bucket].free.offset=sz;
  521.         for (i=1;i< (nblks);i++)          /* fill header of blocks */
  522.                 {
  523.                 poke(page,i*sz,page);
  524.                 poke(page,i*sz +2,(i+1)*sz);    
  525.                 }
  526.         poke(page,nblks*sz,0);            /* last block -> NULL */
  527.         poke(page,nblks*sz+2,0);
  528.         }
  529.  
  530. else    {           /* 2.nd case : one selectors per 64 KB */
  531.         if ((handle=GlobalAlloc(sz,&memaddress))==0) return NULL ;
  532.         nsel=(WORD) ((sz-1)>>16);         /* nsel = number of selectors */
  533.         nsel++;
  534.         if ((page=AllocLDT(nsel))==0) {   /* no more selectors? */
  535.                 GlobalFree(handle) ;      /* free memory */
  536.                 return NULL;
  537.                 }
  538.         if (sz>0x10000L) sz=0x10000L ;    /* divide in 64KB */
  539.         nextpage=page;
  540.         for (i=1;i<=nsel;i++) {
  541.                 if (SetBaseAddress(nextpage,memaddress)==-1) 
  542.                         printf("error set Base\n");
  543.                 if (SetLimit(nextpage,sz-1)==-1) 
  544.                         printf("error set Limit\n");
  545.                 memaddress+=0x10000L ;
  546.                 nextpage+=SelInc();       /* get next selector number */
  547.                 }
  548.         }
  549. return (MK_FP(page,0)) ;
  550. }
  551.  
  552. void far *extmalloc(DWORD nbytes)
  553. {
  554.         WORD bucket, n=0 ;
  555.         DWORD amt ;
  556.         union overhead far *fp;
  557.  
  558.         if (nbytes == 0 ) return NULL;
  559.         nbytes+= sizeof(union overhead) ;
  560.  
  561.         if (nbytes <= PAGESIZE ) {              /* nbytes <= PAGE */
  562.                 amt = 4;                        /* bucket = 1..12 */
  563.                 bucket = 0;
  564.                 n = 0 ; 
  565.                 } 
  566.         else    {                               /* nbytes > PAGE   */
  567.                 amt = PAGESIZE;                 /* bucket = 13..30 */
  568.                 bucket = PAGEBUCKET;
  569.                 n=PAGESIZE;
  570.                 }
  571.         while (nbytes > amt + n) {
  572.                 amt <<= 1;
  573.                 if (amt == 0)
  574.                         return NULL;
  575.                 bucket++;
  576.                 }
  577.  
  578.         if (nextf[bucket].free.page == 0) {          /* no mem in list */
  579.                 fp=(union overhead far *)morepages(bucket);
  580.                 if ((fp) == NULL)                    /* no mem from dpmi */
  581.                         return NULL;
  582.                 }
  583.         else    {                               /* mem available in list */
  584.                 /* now : nextf[] -> myblock -> nextp */
  585.  
  586.                 /* fp -> myblock */
  587.                 fp=(union overhead far *)MK_FP(nextf[bucket].free.page,nextf[bucket].free.offset);
  588.                 /* nextf[] -> nextp */
  589.                 nextf[bucket].free.page  =fp->free.page;
  590.                 nextf[bucket].free.offset=fp->free.offset;
  591.                 }
  592.         fp->use.magic= MAGIC ;
  593.         fp->use.index= bucket;
  594.         return ((void far *)(fp+1));
  595. }
  596.  
  597. void extfree(void far *p)
  598. {
  599.     union overhead far *fp ;
  600.     WORD bucket ;
  601.  
  602.         fp=(union overhead far *)p - 1;            /* get header */
  603.         if (fp->use.magic!= MAGIC) return ;        /* bad pointer */
  604.         bucket = fp->use.index ;                   /* get size of pointer */
  605.                                  /* nextf[] -> nextp */
  606.                                  /* wanted : nextf[] -> fp -> nextf */
  607.         fp->free.page=nextf[bucket].free.page;
  608.         fp->free.offset=nextf[bucket].free.offset;
  609.         nextf[bucket].free.page = FP_SEG(fp);
  610.         nextf[bucket].free.offset=FP_OFF(fp);
  611. }
  612.